﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Komodex.NETMF.TweetingBreathalyzer.Helpers;
using Komodex.NETMF.MicroTweet;

namespace Komodex.NETMF.TweetingBreathalyzer
{
    public class Program
    {
        #region Fields

        // LEDs
        protected static OutputPort onboardLED = new OutputPort(Pins.ONBOARD_LED, false);
        protected static OutputPort redLED = new OutputPort(Config.RedLEDPin, false);
        protected static OutputPort greenLED = new OutputPort(Config.GreenLEDPin, false);
        protected static RGBLED rgbLed = new RGBLED(Config.RGBRedPin, Config.RGBGreenPin, Config.RGBBluePin, Config.RGBInverted);

        // Button
        protected static InterruptPort button = new InterruptPort(Config.ButtonPin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);

        // Sensor
        protected static AnalogInput SensorInput;
        protected static int SensorMinValue;

        // Twitter
        protected static bool timeUpdated = false;
        protected static TwitterClient twitterClient = null;

        #endregion

        public static void Main()
        {
            // Button
            button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);

            // LEDs
            rgbLed.SetColor(0, 0, 100);
            redLED.Write(true);

            // Update the clock in a separate thread
            Thread clockThread = new Thread(UpdateTime);
            Debug.Print("Updating date/time...");
            clockThread.Start();

            // Countdown to abort the clock update thread if the NTP server cannot be reached
            int countdown = 20;

            // Blink the blue LED while the time is updating
            while (clockThread.IsAlive)
            {
                rgbLed.SetColor(0, 0, 0);
                Thread.Sleep(200);
                rgbLed.SetColor(0, 0, 100);
                Thread.Sleep(200);
                if (countdown-- < 0)
                    clockThread.Abort();
            }

            // If the time update was successful, set up the TweetBot
            if (timeUpdated)
            {
                redLED.Write(false);
                twitterClient = new TwitterClient(Config.ConsumerKey, Config.ConsumerSecret, Config.UserToken, Config.UserTokenSecret);
                twitterClient.DebugMessage += new DebugMessageEventHandler(tweetBot_DebugMessage);
            }

            // Time update successful, print the current date/time to the debug console
            Debug.Print("Current date/time: " + DateTime.Now.ToString());

            onboardLED.Write(true);

            // Sensor
            SensorInput = new AnalogInput(Config.SensorPin);

            // Wait for the sensor to heat up
            rgbLed.FullSweep(RGB.Blue, RGB.Red, 50);

            // Establish the sensor minimum value
            SensorMinValue = SensorInput.Read();
            if (SensorMinValue >= Config.SensorMaxValue) // Error
                ErrorLoop();

            while (true)
            {
                int sensorValue = GetSensorValue();
                rgbLed.SetTwoColorRange(RGB.Green, RGB.Red, sensorValue);
                Thread.Sleep(15); // 15ms delay means the value is read about 60 times/sec
            }
        }

        static void UpdateTime()
        {
            timeUpdated = false;
            timeUpdated = NTP.UpdateTimeFromNTPServer(Config.NTPServer);
        }

        static void tweetBot_DebugMessage(object sender, DebugMessageEventArgs e)
        {
            Debug.Print(e.Message);
        }

        static void button_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            if (twitterClient == null)
                return;
            greenLED.Write(true);

            int sensorValue = GetSensorValue();

            string message;
            if (sensorValue < 20)
                message = "No alcohol detected";
            else if (sensorValue < 40)
                message = "Tipsy";
            else if (sensorValue < 60)
                message = "Drunk";
            else if (sensorValue < 80)
                message = "Whoa! #WINNING";
            else
                message = "x_x";

            DateTime adjustedTime = DateTime.Now + new TimeSpan(Config.TimeOffset, 0, 0);

            message += " at " + adjustedTime.ToString("h:mm:ss tt");

            try
            {
                twitterClient.SendTweet(message);
            }
            catch (Exception e)
            {
                Debug.Print(e.ToString());
            }

            greenLED.Write(false);
            button.ClearInterrupt();
        }

        public static void ErrorLoop()
        {
            onboardLED.Write(false);

            // Flash the red LED
            while (true)
            {
                rgbLed.SetColor(0, 0, 0);
                Thread.Sleep(1000);
                rgbLed.SetColor(100, 0, 0);
                Thread.Sleep(1000);
            }
        }

        public static int GetSensorValue()
        {
            int rawValue;
            lock (SensorInput)
            {
                rawValue = SensorInput.Read();
            }
            int adjustedValue = (rawValue - SensorMinValue) * 100;
            int result = adjustedValue / (Config.SensorMaxValue - SensorMinValue);
            return result;
        }

    }
}
